/*
 * linux 另一种定时器:POSIX间隔式定时器
 * *********************************************************************************
 * @ 创建定时器
 *     int timer_creaate(clockid_t clockid, struct sigevent *evp, timer_t *timerid);
 *     return : 0,success; -1 error
 *     clockid:可以是以下几类
 *                  CLOCK_REALTIME  :可设定的系统级实时时钟
 *                  CLOCK_MONNOTONIC :不可设定的恒定态时钟
 *                  CLOCK_PROCESS_CPUTIME_ID:每进程CPU时间的时钟
 *                  CLOCK_THREAD_CPUTIME_ID:每进程CPU时间的时钟 
 *     evp:
 *          union sigval{
 *                  int sigval_int;
 *                  void *sival_ptr;
 *              };
 *          struct sigevent{
 *              int sigev_notify; //SIGEV_NONE,SIGEV_SIGNAL,SIGEV_THREAD,SIGEV_THREAD_ID
 *              int sigev_signo;
 *              union sigval sigev_value;
 *              union{
 *                  pid_t _tid;
 *                  struct{
 *                      void (*function)(union sigval);
 *                      void *_attribute;
 *                  }_sigev_thread;
 *              }_sigev_un;
 *          };
 *   timerid:返回timerid所指向的缓冲区防止定时器句柄，待后续调用中指定该定时器
 ********************************************************************************* 
 * @ 启动或停止一个定时器
 *  int timer_settimer(timer_t timerid, int flags, const struct itimerspec *value,
 *                      struct itimerspec *old_value);
 *  return 0, succ , -1 fail
 *  flags:一般为0
 *  value 和 old_value 和settimer（）的一致
 * 
 * *****************************************************************************
 * @ 获取定时器的当前值
 *   int timer_gettime(timer_t timerid, struct itimerspec *curr_value)
 *   return: 0:succ, -1:fail
 *   curr_value:返回当前定时器的时间间隔以及下次定时器到期的时间
 * *****************************************************************************
 * @ 删除定时器
 *   int timer_delete(timer_t timerid)
 *   return: 0:succ, -1:fail
 * ******************************************************************************
 */

//1...signal method
#if 0
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>

#define CLOCKID CLOCK_REALTIME

void sig_handler(int signo)
{
    printf("timer_signal function! %d\n", signo);
}

int main()
{
    //XXX int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
    // signum--指定的信号编号，可以指定SIGKILL和SIGSTOP以外的所有信号编号
    // act结构体--设置信号编号为signum的处理方式
    // oldact结构体--保存上次的处理方式
    //
    // struct sigaction
    // {
    // void (*sa_handler)(int);         //信号响应函数地址
    // void (*sa_sigaction)(int, siginfo_t *, void *);   //但sa_flags为SA——SIGINFO时才使用
    // sigset_t sa_mask;         //说明一个信号集在调用捕捉函数之前，会加入进程的屏蔽中，当捕捉函数返回时，还原
    // int sa_flags;
    // void (*sa_restorer)(void);   //未用
    // };
    //
    timer_t timerid;
    struct sigevent evp;

    struct sigaction act;
    memset(&act, 0, sizeof(act));
    act.sa_handler = sig_handler;
    act.sa_flags = 0;

    // XXX int sigaddset(sigset_t *set, int signum);  //将signum指定的信号加入set信号集
    // XXX int sigemptyset(sigset_t *set);          //初始化信号集

    sigemptyset(&act.sa_mask);

    if (sigaction(SIGUSR1, &act, NULL) == -1)
    {
        perror("fail to sigaction");
        exit(-1);
    }

    memset(&evp, 0, sizeof(struct sigevent));
    evp.sigev_signo = SIGUSR1;
    evp.sigev_notify = SIGEV_SIGNAL;
    if (timer_create(CLOCK_REALTIME, &evp, &timerid) == -1)
    {
        perror("fail to timer_create");
        exit(-1);
    }

    struct itimerspec it;
    it.it_interval.tv_sec = 2;
    it.it_interval.tv_nsec = 0;
    it.it_value.tv_sec = 1;
    it.it_value.tv_nsec = 0;
    if (timer_settime(timerid, 0, &it, 0) == -1)
    {
        perror("fail to timer_settime");
        exit(-1);
    }

    pause();

    return 0;
}

//new thread method
#else
#include <stdio.h>
#include <signal.h>
#include <time.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#define CLOCKID CLOCK_REALTIME

void timer_thread(union sigval v)
{
    printf("timer_thread function! %d\n", v.sival_int);
}

int main()
{
    // XXX int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid);
    // clockid--值：CLOCK_REALTIME,CLOCK_MONOTONIC，CLOCK_PROCESS_CPUTIME_ID,CLOCK_THREAD_CPUTIME_ID
    // evp--存放环境值的地址,结构成员说明了定时器到期的通知方式和处理方式等
    // timerid--定时器标识符
    timer_t timerid;
    struct sigevent evp;
    memset(&evp, 0, sizeof(struct sigevent)); //清零初始化

    evp.sigev_value.sival_int = 111;          //也是标识定时器的，这和timerid有什么区别？回调函数可以获得
    evp.sigev_notify = SIGEV_THREAD;          //线程通知的方式，派驻新线程
    evp.sigev_notify_function = timer_thread; //线程函数地址

    if (timer_create(CLOCKID, &evp, &timerid) == -1)
    {
        perror("fail to timer_create");
        exit(-1);
    }

    // XXX int timer_settime(timer_t timerid, int flags, const struct itimerspec *new_value,struct itimerspec *old_value);
    // timerid--定时器标识
    // flags--0表示相对时间，1表示绝对时间
    // new_value--定时器的新初始值和间隔，如下面的it
    // old_value--取值通常为0，即第四个参数常为NULL,若不为NULL，则返回定时器的前一个值

    //第一次间隔it.it_value这么长,以后每次都是it.it_interval这么长,就是说it.it_value变0的时候会装载it.it_interval的值
    struct itimerspec it;
    it.it_interval.tv_sec = 1;
    it.it_interval.tv_nsec = 0;
    it.it_value.tv_sec = 1;
    it.it_value.tv_nsec = 0;

    if (timer_settime(timerid, 0, &it, NULL) == -1)
    {
        perror("fail to timer_settime");
        exit(-1);
    }

    pause();

    return 0;
}
#endif